package com.lse_api.control;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lse_api.config.security.SecurityUtil;
import com.lse_api.entity.*;
import com.lse_api.exception.LseException;
import com.lse_api.service.*;
import com.lse_api.utils.*;
import com.lse_api.utils.pdfutil.stringutil.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * LSE API后台控制器
 *
 * @author 祁雪
 */
@RequestMapping(value = "/lseapi/backapi")
@Controller
public class BackgroundController extends LseException implements ReturnMsg {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private GroupListService groupListService;

    @Autowired
    private GroupUserService groupUserService;

    @Autowired
    private GroupUserAuditService groupUserAuditService;

    @Autowired
    private GroupProjectService groupProjectService;

    @Autowired
    private LsePermissionsService lsePermissionsService;

    @Autowired
    private LseRolePermissionsService lseRolePermissionsService;

    @Autowired
    private LseUserRoleService lseUserRoleService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectApiService projectApiService;

    @Autowired
    private ProjectApiParpamService projectApiParpamService;

    @Autowired
    private ProjectLogService projectLogService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private TokenService tokenService;

    @Value("${web.upload-path}")
    public String path;

    /**
     * home LSE api 后台主页大屏
     *
     * @return
     */
    @RequestMapping(value = "/home")
    @ResponseBody
    @PreAuthorize("hasAnyRole('ADMIN','TOURISTS')")
    public Status home() {

        // 读取项目总数
        int projectNum = projectService.count();

        // 读取项目日志总数
        int logNum = projectLogService.count();

        // 读取项目组总数
        int groupNum = groupListService.count();

        // 读取用户总数
        int userNum = userInfoService.count();

        // 读取token列表(最近更新的前10)
        PageHelper.startPage(1, 10);
        QueryWrapper<Token> tokenQueryWrapper = new QueryWrapper<>();
        tokenQueryWrapper.orderByDesc("token_time");
        List<Token> tokens = tokenService.list(tokenQueryWrapper);

        // 读取项目API列表并统计折线图(每天次数)
        List<ProjectApi> projectApis = projectApiService.list();

        // 读取api总数
        int apiNum = projectApis.size();

        Map<String, Integer> apiMap = new LinkedHashMap<>();

        projectApis.stream()
                .sorted(Comparator.comparing(ProjectApi::getCreateTime))
                .forEach(projectApi -> {
                    String time = DateUtil.getOneDateTime(projectApi.getCreateTime(), "yyyy-MM-dd");

                    if (apiMap.get(time) != null) {
                        apiMap.put(time, apiMap.get(time) + 1);
                    } else {
                        apiMap.put(time, 1);
                    }
                });

        // 读取工程日志文件夹
        Map<String, List<String>> logsMap = FileTree.getTree(path + "log");

        // 返回已登录者用户信息
        UserInfo userInfo = userInfoService.getUserInfoByUserId(UserInfoCheck.checkAddress(2),
                SecurityUtil.getName());

        // 读取登录者权限返回模式(ADMIN.管理员模式 TOURISTS.游客模式)
        List<String> list = SecurityUtil.getAuth();

        // 1.TOURISTS 0.ADMIN
        int roleNum = 1;

        if (list.contains("ROLE_ADMIN")) {
            roleNum = 0;
        }

        Map<String, Object> dataMap = new HashMap<>();
        // 项目数量
        dataMap.put("projectNum", projectNum);
        // 项目日志数量
        dataMap.put("logNum", logNum);
        // 项目组数量
        dataMap.put("groupNum", groupNum);
        // 用户数量
        dataMap.put("userNum", userNum);
        // token列表
        dataMap.put("tokens", tokens);
        // api数量
        dataMap.put("apiNum", apiNum);
        // api折线图 x轴
        dataMap.put("apiMapX", apiMap.keySet());
        // api折线图 y轴
        dataMap.put("apiMapY", apiMap.values());
        // 工程日志目录
        dataMap.put("logsMap", logsMap);
        // 用户信息
        dataMap.put("userInfo", userInfo);
        // 访问模式 0.管理员 1.游客
        dataMap.put("role", roleNum);

        return Status.success(dataMap);
    }

    /**
     * 从已创建的用户列表中赋予角色(只能赋予游客权限)
     * user: 用户ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/giveTouristsRole")
    @ResponseBody
    public Status giveTouristsRole() {

        String userId = request.getParameter("user");

        if (StringUtils.isEmpty(userId)) {
            return Status.error(BACK_USER_IS_NULL);
        }

        if (userId.equalsIgnoreCase(SecurityUtil.getName())) {
            return Status.error(BACK_USER_IS_ME);
        }

        QueryWrapper<LseUserRole> lseUserRoleQueryWrapper = new QueryWrapper<>();
        lseUserRoleQueryWrapper.eq("user_id", userId)
                .eq("role_id", 3);

        LseUserRole lseUserRole = lseUserRoleService.getOne(lseUserRoleQueryWrapper);

        if (lseUserRole == null) {

            lseUserRole = new LseUserRole();
            lseUserRole.setCreateTime(new Date());
            lseUserRole.setUserId(userId);
            lseUserRole.setRoleId(3);
            boolean flag = lseUserRoleService.saveOrUpdate(lseUserRole);
            return flag ? Status.success(BACK_ROLE_GIVE_SUCCESS) : Status.error(BACK_ROLE_GIVE_FAILURE);
        } else {
            return Status.error(BACK_HAVE_ROLE);
        }

    }

    /**
     * 读取全部项目组列表
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getGroupList")
    @ResponseBody
    public Status getGroupList() {

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<GroupList> groups = groupListService.list();

        PageInfo<GroupList> pageInfo = new PageInfo<>(groups);

        return Status.success(pageInfo);

    }

    /**
     * 读取指定项目组下的用户列表
     * group: 项目组ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getUserListByGroup")
    @ResponseBody
    public Status getUserListByGroup() {

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");
        String groupId = request.getParameter("group");

        if (StringUtils.isEmpty(groupId)) {
            return Status.error(API_GROUP_ID);
        }

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<GroupUser> list = groupUserService.getUserListByGroup(groupId);

        PageInfo<GroupUser> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);

    }

    /**
     * 读取指定项目组旗下项目
     * group: 项目组id
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getProjectByGroup")
    @ResponseBody
    public Status getProjectByGroup() {

        String groupId = request.getParameter("group");

        if (StringUtils.isEmpty(groupId)) {
            return Status.error(API_GROUP_ID);
        }

        List<Project> list = projectService.getProjectListByGroup(groupId);

        return Status.success(list);

    }

    /**
     * 读取项目组申请记录
     * group: 项目组ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getAuditListByGroup")
    @ResponseBody
    public Status getAuditListByGroup() {

        String groupId = request.getParameter("group");
        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        if (StringUtils.isEmpty(groupId)) {
            return Status.error(API_GROUP_ID);
        }

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<GroupUserAudit> list = groupUserAuditService.getAuditListByGroup(groupId);

        PageInfo<GroupUserAudit> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);
    }

    /**
     * 读取项目旗下API
     * project: 项目ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @ResponseBody
    @RequestMapping(value = "/getApiListByProject")
    public Status getApiListByProject() {

        String projectId = request.getParameter("project");
        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        if (StringUtils.isEmpty(projectId)) {
            return Status.error(API_PROJECT_ID);
        }

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<ProjectApi> list = projectApiService.getApiListByProject(projectId);

        PageInfo<ProjectApi> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);

    }

    /**
     * 读取全部项目列表
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getProjectList")
    @ResponseBody
    public Status getProjectList() {

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<Project> list = projectService.list();

        PageInfo<Project> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);
    }

    /**
     * 根据项目读取项目日志
     * project: 项目ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @ResponseBody
    @RequestMapping(value = "/getLogsByProject")
    public Status getLogsByProject() {

        String projectId = request.getParameter("project");

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        if (StringUtils.isEmpty(projectId)) {
            return Status.error(API_PROJECT_ID);
        }

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<ProjectLog> list = projectLogService.getLos(projectId);

        PageInfo<ProjectLog> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);
    }

    /**
     * 绘制项目统计图(折线图: api数量|日志数量 / 天数)
     * project: 项目ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getStatisticalByProject")
    @ResponseBody
    public Status getStatisticalByProject() {

        String projectId = request.getParameter("project");

        if (StringUtils.isEmpty(projectId)) {
            return Status.error(API_PROJECT_ID);
        }

        // 读取整个项目API列表
        List<ProjectApi> projectApis = projectApiService.getApiListByProject(projectId);

        // 读取整个项目日志列表
        List<ProjectLog> projectLogs = projectLogService.getLos(projectId);

        Map<String, Integer> apiMap = new LinkedHashMap<>();
        Map<String, Integer> logMap = new LinkedHashMap<>();

        // 按照 yyyy-MM-dd 格式区分每天的数量

        projectApis.forEach(projectApi -> {
            String time = DateUtil.getOneDateTime(projectApi.getCreateTime(), "yyyy-MM-dd");
            if (apiMap.get(time) != null) {
                apiMap.put(time, apiMap.get(time) + 1);
            } else {
                apiMap.put(time, 1);
            }
        });

        projectLogs.forEach(projectLog -> {
            String time = DateUtil.getOneDateTime(projectLog.getLogTime(), "yyyy-MM-dd");
            if (logMap.get(time) != null) {
                logMap.put(time, logMap.get(time) + 1);
            } else {
                logMap.put(time, 1);
            }

        });

        // 遍历两者时间 组成3个List
        List<Integer> apiNums = new ArrayList<>();
        List<Integer> logNums = new ArrayList<>();

        List<String> timeSet = new ArrayList<>();
        if (apiMap.size() > 0) {
            timeSet.addAll(apiMap.keySet());
        }
        if (logMap.size() > 0) {
            timeSet.addAll(logMap.keySet());
        }

        timeSet = timeSet.stream().distinct().collect(Collectors.toList());

        Collections.sort(timeSet, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return DateUtil.getDate(o1).compareTo(DateUtil.getDate(o2));
            }
        });

        timeSet.forEach(time -> {
            apiNums.add(apiMap.get(time) != null ? apiMap.get(time) : 0);
            logNums.add(logMap.get(time) != null ? logMap.get(time) : 0);
        });

        Map<String, Object> map = new HashMap<>();

        map.put("x", timeSet);
        map.put("api", apiNums);
        map.put("log", logNums);

        return Status.success(map);
    }


    /**
     * 绘制项目组统计图(饼状图: 组成员数量/项目数量/成员申请记录数量)
     * group: 项目组ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getStatisticalByGroup")
    @ResponseBody
    public Status getStatisticalByGroup() {

        String groupId = request.getParameter("group");

        if (StringUtils.isEmpty(groupId)) {
            return Status.error(API_GROUP_ID);
        }

        // 读取组成员数量
        QueryWrapper<GroupUser> groupUserQueryWrapper = new QueryWrapper<>();
        groupUserQueryWrapper.eq("group_id", groupId);

        int groupUserNum = groupUserService.count(groupUserQueryWrapper);

        // 读取组内项目数量
        QueryWrapper<GroupProject> groupProjectQueryWrapper = new QueryWrapper<>();
        groupProjectQueryWrapper.eq("group_id", groupId);

        int groupProjectNum = groupProjectService.count(groupProjectQueryWrapper);

        // 读取组内成员申请记录数量
        QueryWrapper<GroupUserAudit> groupUserAuditQueryWrapper = new QueryWrapper<>();

        groupUserAuditQueryWrapper.eq("group_id", groupId);

        int groupUserAuditNum = groupUserAuditService.count(groupUserAuditQueryWrapper);

        Map<String, Integer> map = new HashMap<>();

        map.put("groupUserNum", groupUserNum);
        map.put("groupProjectNum", groupProjectNum);
        map.put("groupUserAuditNum", groupUserAuditNum);

        return Status.success(map);
    }

    /**
     * 读取用户列表
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @ResponseBody
    @RequestMapping(value = "/getUserInfoList")
    public Status getUserInfoList() {

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<UserInfo> list = userInfoService.list();

        PageInfo<UserInfo> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);

    }

    /**
     * 读取token列表
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value = "/getTokenList")
    @ResponseBody
    public Status getTokenList() {

        String pageNo = request.getParameter("pageNo");
        String pageSize = request.getParameter("pageSize");

        Map<String, Integer> map = PageUtil.getPage(pageNo, pageSize);

        PageHelper.startPage(map.get("pageNo"), map.get("pageSize"));

        List<Token> list = tokenService.list();

        PageInfo<Token> pageInfo = new PageInfo<>(list);

        return Status.success(pageInfo);

    }

    /**
     * 清除用户通行证(即删除用户token信息)
     * user: 用户ID
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN')")
    @ResponseBody
    @RequestMapping(value = "/removeTokenByUser")
    public Status removeTokenByUser() {

        String userId = request.getParameter("user");

        if (StringUtils.isEmpty(userId)) {
            return Status.error(BACK_USER_IS_NULL);
        }

        if (userId.equalsIgnoreCase(SecurityUtil.getName())) {
            return Status.error(BACK_USER_IS_ME);
        }

        boolean flag = tokenService.removeById(userId);

        return flag ? Status.success(BACK_TOKEN_DELETE_SUCCESS) : Status.error(BACK_TOKEN_DELETE_FAILURE);

    }


}
